package com.ecar.api.support.util;

import com.ecar.cache.RedisFactory;
import com.ecar.common.datetime.TimeUtil;
import redis.clients.jedis.Jedis;

import java.text.MessageFormat;
import java.util.Date;

/**
 * Redis连接实例，存储数据KEY定义
 * Created by 30 on 2016/8/30.
 */
public class Redis {

	public static final String LOCK_PREFIX = "lock:";

	public static final String DATE = "yyyyMMdd";

	public static final int M5 = 300;
	public static final int M10 = 600;
	public static final int M15 = 900;
	public static final int M30 = 1800;
	public static final int HOUR = 3600;
	public static final int DAY = 86400;

	public static final String NX = "NX";	// 不存在
	public static final String XX = "XX";	// 已存在
	public static final String EX = "EX";	// 秒
	public static final String PX = "PX";	// 毫秒

	public enum K{
		/** 微信api访问token缓存 */
		WX_TOKEN("wx:api:token"),
		/** 广告:moduleId */
		ADS("store:ads:mid:{0}"),
		/** 订票请求接口配置:api.id */
		API("store:api:id:{0}"),
		/** 系统配置:config.key */
		CFG("store:config:key:{0}"),
		/** 模块配置:configModule.key */
		MCFG("store:config:module:key:{0}"),
		/** 保险:moduleId */
		INSR("store:insurance:mid:{0}"),
		/** 微信服务商token */
		H5_TOKEN("pay:h5:access:token"),
		/** 重复请求过滤:md5(ip+token+uri) */
		REQ_FILTER("filter:request:{0}"),
		/** 缓存用户信息:user.id */
		USER("user:id:{0}"),
		/** 缓存用户信息:user.phone */
		USER_PHONE("user:phone:{0}"),
		/** 联系人修改限制:user.id */
		LIMIT_CONTACT("limit:contact:{0}"),
		/** 手机验证码:phone */
		CAPTCHA("captcha:phone:{0}"),
		/** 图形验证码:phone */
		CODE("code:phone:{0}"),
		/** 微信授权临时用户:openid */
		WXAUTH("wxauth:user:{0}"),
		/** 短信发送成功 */
		SMS_SUCCESS("success"),
		/** 短信发送失败 */
		SMS_ERROR("error"),
		/** 用户随机优惠金额 */
		SALES_RAND("user:sales:{0}"),
		/** 乘客每天免费取消订单次数 */
		PASSENGER_COUNTS("passenger:cancelcounts:{0}"),
		/** 预约单分发次数 */
		ORDER_SEND("order:send:{0}"),
		/** 预约单是否已发送 */
		ORDER_SENDED("order:sended:{0}"),
		/** 司机与乘客的距离 */
		ORDER_DISTANCE("order:distance:{1}:{0}"),
		/** 拼车 (0:订单号  1：座位数) */
		ORDER_CARPOOL("order:carpool:{0}"),
		/** 航班信息 */
		FLIGHT_INFO("flight:info:{0}"),
		/** 拼车一口价 */
		CARPOOL_INFO("passenger:carpool_info:{0}"),
		/** 超时订单 */
		OVERTIME_ORDER("order:overtime:{0}"),
		/**预约单超时    司机发短信*/
		SMS_DRIVER("order:sms:driver:{0}"),
		/**司机错误登陆次数key(0.日期  1.司机手机号),value:次数*/
		DRIVER_LOGIN("driver:{0}:{1}"),
		/**后台错误登陆次数key(0.日期  1.司机手机号),value:次数*/
		MANAGER_LOGIN("manager:{0}:{1}")
		;

		private String key;
		private String type;
		private int module;
		K(String key) {
			this.key = key;
			this.type = "String";
			this.module = 0;
		}
		K(String key, String type) {
			this.key = key;
			this.type = type;
			this.module = 0;
		}
		K(String key, int module) {
			this.key = key;
			this.type = "String";
			this.module = module;
		}
		K(String key, String type, int module) {
			this.key = key;
			this.type = type;
			this.module = module;
		}
		public String me() {
			return this.key;
		}
		public String to(Date date) {
			return to(TimeUtil.formatTime(date, DATE));
		}
		public String to(Date date, String arg) {
			return to(TimeUtil.formatTime(date, DATE), arg);
		}
		public String to(int arg) {
			return to(String.valueOf(arg));
		}
		public String to(int arg1, int arg2) {
			return to(String.valueOf(arg1), String.valueOf(arg2));
		}
		public String to(int arg1, int arg2, int arg3) {
			return to(String.valueOf(arg1), String.valueOf(arg2), String.valueOf(arg3));
		}
		public String to(String... args) {
			return MessageFormat.format(this.key, args);
		}
		public boolean eq(int module) {
			return this.module == module;
		}
		public boolean eq(String type) {
			return this.type.equalsIgnoreCase(type);
		}
	}

	public static RedisFactory c = RedisFactory.getInstance();

	public static boolean lock(String key, int expire) {
		if (isLocked(key)) return false;

		int count = 0;
		String result = null;
		long expireAt = System.currentTimeMillis() + expire * 1000;
		do {
			if (count >= 3) break;
			result = c.set(LOCK_PREFIX + key, String.valueOf(expireAt), NX, EX, expire);
			++count;
		} while (!"ok".equalsIgnoreCase(result));

		return "ok".equalsIgnoreCase(result);
	}

	public static boolean isLocked(String key) {
		key = LOCK_PREFIX + key;
		return c.exists(LOCK_PREFIX + key);
	}

	public static int unlock(String key) {
		return c.del(LOCK_PREFIX + key).intValue();
	}

	public static boolean lock(Jedis jedis, String key, int expire) {
		if (isLocked(jedis, key)) return false;

		int count = 0;
		String result = null;
		long expireAt = System.currentTimeMillis() + expire * 1000;
		do {
			if (count >= 3) break;
			result = jedis.set(LOCK_PREFIX + key, String.valueOf(expireAt), NX, EX, expire);
			++count;
		} while (!"ok".equalsIgnoreCase(result));

		return "ok".equalsIgnoreCase(result);
	}

	public static boolean isLocked(Jedis jedis, String key) {
		key = LOCK_PREFIX + key;
		return jedis.exists(LOCK_PREFIX + key);
	}

	public static int unlock(Jedis jedis, String key) {
		return jedis.del(LOCK_PREFIX + key).intValue();
	}

	public static Jedis getResource() throws Exception {
		return c.getResource();
	}

	public static void release(Jedis resource) {
		if (resource != null) c.releaseResource(resource);
	}

}
